/*
 * VectorRegistros.h
 *
 *	Contiene los registros que forman al nodo y las operaciones necesarias
 *	para trabajar con ellos en un arbol B+
 */

#ifndef VECTORREGISTROS_H_
#define VECTORREGISTROS_H_

#include <list>
#include "RegistroAbstracto.h"
#include "RegistroInterno.h"
#include "ArbolCommons.h"

using namespace ArbolCommons;

class VectorRegistros {
	private:
		size_t _espacioLibre;
		size_t _cantBytesOcupados;
		std::list<RegistroAbstracto*> _listRegs;

		// Esto es feo, pero facil... 
		// se guarda la referencia al hijo mas derecho del nodo interno
		// o si es una hoja una referencia a la siguiente hoja de datos
		unsigned long int _referenciaExtra;

		// Una referencia al lugar en disco que ocupa el nodo
		unsigned long int _selfRef;

		// Para evaluar la existencia de underflow
		bool hayUnderFlow();

		// Para las busquedas internas
		unsigned long int busquedaNodoHoja(unsigned long int id, bool inexacta);
		unsigned long int busquedaNodoInterno(unsigned long int id);
	public:
		VectorRegistros(size_t tamBytes, unsigned long int selfRef);
		~VectorRegistros();

		// Inserta el registro apuntado al vector
		resulOperacion addRegistro(RegistroAbstracto* reg);

		// Quita el registro que contiene el id señalado del vector
		resulOperacion removeRegistro(unsigned long int id);

		// Devuelve una referencia al registro que contiene el id señalado en el vector,
		// NO ES UNA COPIA, ES EL ALMACENADO. NULL si no existe 
		RegistroAbstracto* getRegistro(unsigned long int id);

		// Señala si existe un registro con el id indicado en el vector
		bool existeRegistro(unsigned long int id);

		// Devuelve la cantidad de bytes ocupados por todos los registros del vector
		size_t getSize();

		// Devuelve la cantidad de registros guardados en el vector
		size_t getCantRegistros();

		// Permite acceder al registro interno usando acceso directo dentro del vector
		RegistroAbstracto* operator[](int i);

		/* Busqueda de referencia a registro:
		 * El valor de retorno depende del tipo del nodo:
		 * 	Si es una hoja: devuelve la posicion del registro dentro del vector
		 *	Si es un nodo interno: devuelve una referencia al bloque en disco que contiene
		 * 		el registro buscado
		 *
		 *	Si la busqueda es en nodo interno siempre devuelve una referencia al nodo
		 *		que deberia contener el "id" pedido 
		 *	Si la busqueda es en una hoja, es exacta y no encontro el registro devuelve -1 
		 * */
		unsigned long int buscarRegistro(unsigned long int id, int nivel, bool inexacta=false);

		// Devuelve la referencia de disco del nodo
		unsigned long int getSelfReference();

		// Devuelve la referencia en disco al siguiente nodo hoja. SOLO PARA NODOS HOJAS
		unsigned long int getRefProxNodo(int nivelNodo);

		// Setea la referencia al proximo nodo, SOLO NODOS HOJAS
		void setRefProxNodo(unsigned long int ref, int nivelNodo);

		// Devuelve la referencia derecha, SOLO PARA NODOS INTERNOS
		unsigned long int getRefenciaDerecha(int nivelNodo);

		// Setea la referencia al hijo mas "derecho", SOLO NODOS INTERNOS
		void setRefenciaDerecha(unsigned long int refDerecha, int nivelNodo);

		// Divide en forma equitativa los registros entre los dos contenedores
		// y devuelve el registro que se debe promover
		RegistroInterno* split(VectorRegistros* newContenedor, int nivelNodo);

		// Envia todos los registros al nuevo contenedor IZQUIERDO (o menor)
		// El contenedor actual queda vacio y debe ser borrado
		RegistroInterno* mergeTo(VectorRegistros* nuevoContenedor, int nivelNodo);

		/* Serialización de registros:
		 * 	Para serializar los registros de forma eficiente es necesario almazenar
		 * 	cierta metadata, en este caso seria:
		 * 		(tamDatos;cantRegistros;dataReg0;...)
		 * 	donde:
		 * 		tamDatos: es el tamaño total opcupado por los datos
		 * 		cantRegistros: la cantidad de registros que fueron serializados
		 * 		dataReg0: los datos del registro 0
		 * */

		// Carga todos los registros serializados en la memoria apuntada
		void pack(char* &data);

		// Toma un bloque de memoria y extrae del mismo todos los registros
		void unpack(char* data, datosArchivados tipo, bool esHoja);
};


#endif /* VECTORREGISTROS_H_ */
